Stripeのオンライン決済をTypescriptで実装する(Charges)
クレジットカードでの都度決済をStripeで実装するときはPAYMENTという機能を使います。
今回はStripeのオンライン決済を実装する際のサーバー側の一通りの操作をTypescriptで実装してみます。
Stripe Paymentsについて
StripeではCheckoutというStripeが提供する決済フォームにリダイレクトする機能があります。
ここでは自前のクレジットカード決済フォームで決済するケースを想定して、Cherge APIを使う前提で進めていきます。
またクライアント側の実装については今回は触れません。
こちらのブログに書いたように、現在ChergesよりPaymentIntentsを使って実装することが推奨されています。
新しく実装される際にはPaymentIntentsを検討してください。
動作確認環境
- stripe node SDK 8.50.0
- @types/stripe: 7.13.23
- Typescript: 3.8.3
インストール
npm install stripe --save npm install @types/stripe –save-dev
importとキーの読み込み
import Stripe from 'stripe'; const stripe = new Stripe('sk_test_xxxxxx');
バージョニング
StripeではSDKのバージョンとは別に実行するStripe APIのバージョンを切り替えることができます。
ちなみに、以下のように指定することでAPIのバージョンを切り替えることができます。
const stripe = new Stripe('sk_test_xxxxxx', { apiVersion: '2020-03-02' });
未指定の場合はStripeアカウントに設定されているバージョンがデフォルトとして適用されます。
デフォルトのバージョンを切り替えたい場合はダッシュボードの 開発
-> APIバージョン
のところから切り替えられます。
各バージョンのアップデート内容はこちらから確認して下さい。
ここでは現時点(2020/06/16)の最新版である 2020-03-02
を使っています。
各操作
カスタマーの登録 (customers.create)
const createCustomer = async (options: Stripe.customers.ICustomerCreationOptions) => { return await stripe.customers.create(options); }
Token or Sources APIを使用して取得した source
で、顧客作成とともにカード登録を行います。
サーバー側の動作のみ確認したい場合は、Stripeで用意されているテストトークンを利用しましょう。
tok_jp
でVISA・tok_jcb
でJCBのカードと見立ててテストができます。詳しくはTesting ドキュメントで確認してください。
カスタマー登録時には他にもオプションがあってemailを登録すると、Stripeから領収書メールを自動送信したりできます。
カードの登録 (customers.createSource)
const createSource = async (customerId: string, source: string) => { return await stripe.customers.createSource(customerId, { source }); }
sourceにはクライアント向けのJSライブラリで取得したTokenを渡します。
Tokenをサーバー側に渡すことで、サーバー側ではユーザーのカード情報を保持せずにStripeに登録することができます。
カードの削除 (customers.deleteSource)
const deleteSource = async (customerId: string, cardId: string) => { return await stripe.customers.deleteSource(customerId, cardId); }
カード一覧取得 (customers.listSources)
const listSources = async (customerId: string, options: Stripe.customers.ICardSourceListOptions) => { return await stripe.customers.listSources(customerId, options); } const result = await listSources('cus_xxxxxx', { object: 'card'});
請求 (charges.create)
charges.create
で請求を作成します。
新しいカードで決済する
interface chargeOptions { amount: number; currency: 'jpy'; source: string; }; const charge = async (options: chargeOptions) => { return await stripe.charges.create(options); }
登録したカードで決済する
interface chargeOptions { amount: number; currency: 'jpy'; customer: string; }; const charge = async (options: chargeOptions) => { return await stripe.charges.create(options); };
オーソリを追加する
請求を作成する際に決済にオーソリを追加することができます。
決済確定までに何らかの処理を挟みたい場合や、返金までの猶予期間を設けたい場合に使いましょう。
charges.create
のoptionsのcaptureをfalseにすることで、決済を確定させずに決済承認のみを発行することができます。
const charge = async (options: Stripe.charges.IChargeCreationOptions) => { return await stripe.charges.create(options); }; const options = { amount: 100, currency: 'jpy', customer: 'cus_xxxxxx', capture: false }; const result = await charge(options);
決済の確定 (charges.capture)
charges.create
の時にcaptureを分離した場合は、charges.capture
で決済を確定します。
const capture = async (chargeId: string, options: Stripe.charges.IChargeCaptureOptions) => { return await stripe.charges.capture(chargeId, options); };
返金 (refunds.create)
返金はrefunds.create
で実行します。
オーソリでもcapture済でもrefundで返金できますが、capture済の場合加盟店手数料がかかります。
const refund = async (options: Stripe.refunds.IRefundCreationOptionsWithCharge) => { return await stripe.refunds.create(chargeId, options); }; const options = { charge: 'ch_xxxxxx' }; const result = await refund(options);
余談
私の環境での話ですが、@types/stripe: 7.13.23
を@types/node 13.11.0
と併用した時に、以下のコンフリクトが発生してしまいました。
error TS4090: Conflicting definitions for 'node' found at '/path/to/project/src/node_modules/@types/node/ts3.7/index.d.ts' and '/path/to/project/src/node_modules/@types/node/ts3.2/index.d.ts'. Consider installing a specific version of this library to resolve the conflict.
@types/nodeを14.0.1に更新したらエラーが解消しました。